// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// C [author] rhyme_lph
// g [email]  rhymelph@gmail.com
// y [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/address_entity.dart';
import 'package:finance_app/src/entities/company_entity.dart';
import 'package:finance_app/src/entities/current_subscription_entity.dart';
import 'package:finance_app/src/entities/payment_method_entity.dart';
import 'package:finance_app/src/entities/promo_code_entity.dart';
import 'package:finance_app/src/entities/sub_cards_entity.dart';
import 'package:finance_app/src/entities/sub_next_billing_item_entity.dart';
import 'package:finance_app/src/http_service/http_common_service.dart';
import 'package:finance_app/src/http_service/http_company_service.dart';
import 'package:finance_app/src/http_service/http_subscription_service.dart';
import 'package:finance_app/src/page/setting/subscription/sub_payment_page.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/add_promo_code_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/address_bottom_sheet.dart';
import 'package:flutter/material.dart';

class SubPaymentProvider extends BaseProvider<SubNextBillingItemEntity> {
  List<PaymentMethodEntity> paymentMethods = [];
  List<SubCardsEntity> cards = [];
  PromoCodeEntity promoCodeEntity;

  List<CompanyEntity> billToList = [];

  TextEditingController companyNameController = TextEditingController();
  FocusNode companyNameFocusNode = FocusNode();

  String companyAddress;

  TextEditingController unitNumberController = TextEditingController();
  FocusNode unitNumberFocusNode = FocusNode();
  TextEditingController postalCodeController = TextEditingController();
  FocusNode postalCodeFocusNode = FocusNode();
  TextEditingController contactNameController = TextEditingController();
  FocusNode contactNameFocusNode = FocusNode();
  TextEditingController phoneNumberController = TextEditingController();
  FocusNode phoneNumberFocusNode = FocusNode();

  CompanyEntity currentCompany = Config.currentCompany;
  String countryCode = '+65';
  SubCardsEntity currentSelectCard;

  PlansItemEntity plan;
  String billingPeriod;
  int billId;
  int companyId;

  // CountryCodesWidget code  =;

  @override
  Future get dataFuture =>
      HttpSubscriptionService.getNextBilling(plan.id, currentCompany.id);

  void onNavManager() {
    Routes.navigateTo(RouterGenProviders.subPaymentMethodManagerPage);
  }

  @override
  void initState() {
    super.initState();
    _loadPaymentMethod();
    _loadAvailableCompany();
    loadCards();
  }

  void onNavPay(String paymentMethod, [isSelectCard = false]) async {
    String companyName;
    String companyAddress;
    String unitNumber;
    String postalCode;
    String contactName;
    String phoneNumber;
    String countryCode;

    if (companyId == null) {
      companyId = currentCompany.id;
    }

    if (currentCompany == billToList.last) {
      companyName = companyNameController.text;
      companyAddress = companyAddress;
      unitNumber = unitNumberController.text;
      postalCode = postalCodeController.text;
      contactName = contactNameController.text;
      phoneNumber = phoneNumberController.text;
      countryCode = this.countryCode;
      companyId = null;
    }
    String paymentUrl;
    int subscriptionId;
    await post(
        HttpSubscriptionService.pay(
          plan.id,
          promoCodeEntity?.code,
          isSelectCard == true ? currentSelectCard?.tokenId?.toString() : '0',
          companyId,
          phoneNumber,
          contactName,
          postalCode,
          unitNumber,
          companyAddress,
          companyName,
          countryCode,
          paymentMethod,
          billId,
        ),
        loadingTip: S.current.loading,
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      paymentUrl = result.data['data']['payment_url'];
      subscriptionId = result.data['data']['subscription_id'];
    });
    if (paymentUrl != null) {
      final result =
          await Routes.navigateTo(RouterGenProviders.webViewPage, params: {
        'url': paymentUrl,
      });
      if (result is Map && result['isSeeInvoice'] == true) {
        //跳转到 See Invoice
        await post(HttpSubscriptionService.getCompaniesSubscription(),
            autoHandler: AutoHandler.Toast,
            loadingTip: S.current.loading, onSuccess: (result) async {
          CurrentSubscriptionEntity entity =
              getEntityFromResult<CurrentSubscriptionEntity>(result);
          RProvider.myProvider.globalMap[ConfigKey.currentSubscription] =
              entity;
          await RProvider.myProvider.updateGlobalMap();
        });
        obtainContext?.call((context) {
          Navigator.of(context).pop(true);
          Routes.navigateTo(RouterGenProviders.subInvoicePage, params: {
            'id': subscriptionId,
          });
        });
      } else if (result is Map && result['isSuccess'] == true) {
        obtainContext?.call((context) async {
          await post(HttpSubscriptionService.getCompaniesSubscription(),
              autoHandler: AutoHandler.Toast,
              loadingTip: S.current.loading, onSuccess: (result) async {
            CurrentSubscriptionEntity entity =
                getEntityFromResult<CurrentSubscriptionEntity>(result);
            RProvider.myProvider.globalMap[ConfigKey.currentSubscription] =
                entity;
            await RProvider.myProvider.updateGlobalMap();
          });
          Navigator.of(context).pop(true);
        });
      }
    }
  }

  // void onConfirm() {
  //   obtainContext?.call((context) async {
  //     await showPaymentProcessedSuccessBottomSheet(context, onGotIt: () {
  //       Routes.navigateTo(RouterGenProviders.subInvoicePage, replace: true);
  //     });
  //   });
  // }

  void _loadPaymentMethod() {
    post(HttpSubscriptionService.getSubscriptionsPaymentMethods(),
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      paymentMethods = getEntityFromResult<List<PaymentMethodEntity>>(result);
      // paymentMethods.removeWhere((element) => element.value == 'CC');
      update();
    });
  }

  void loadCards([bool isShowDialog = false]) {
    post(HttpSubscriptionService.getSubscriptionsCards(),
        autoHandler: AutoHandler.Toast,
        loadingTip: isShowDialog == true ? S.current.loading : null,
        onSuccess: (result) {
      cards = getEntityFromResult<List<SubCardsEntity>>(result);
      if (cards.length > 0) {
        currentSelectCard = cards.firstWhere(
            (element) => element.isDefault == 1,
            orElse: () => null);
      }
      update();
    });
  }

  void onAddPromoCode() {
    obtainContext?.call((context) async {
      final result = await showAddPromoCodeBottomSheet(
          context, promoCodeEntity?.code, (text) async {
        bool isSuccess = false;
        await post(HttpSubscriptionService.checkCoupon(text),
            loadingTip: S.current.loading, onSuccess: (result) {
          isSuccess = true;
          promoCodeEntity = getEntityFromResult<PromoCodeEntity>(result);
        });
        if (isSuccess == false) {
          promoCodeEntity = null;
        }
        return isSuccess;
      });
      if (result == true) {
        promoCodeEntity = null;
      }
      update();
    });
  }

  void onChangeBillTo(CompanyEntity value) {
    currentCompany = value;
    update();
  }

  void onChangeCountryCode(value) {
    countryCode = value;
    update();
  }

  Future<void> _loadAvailableCompany() async {
    await post(HttpCompanyService.companyList(), onSuccess: (result) async {
      final companies = getEntityFromResult<List<CompanyEntity>>(result);
      CompanyEntity entity;
      for (final item in companies) {
        if (item.id.toString() == Config.userProfile.defaultCompanyId) {
          entity = item;
          break;
        }
      }
      RProvider.myProvider.globalMap[ConfigKey.currentCompany] = entity;
      await RProvider.myProvider.updateGlobalMap();
      currentCompany = entity;
      billToList = companies;
      billToList.add(CompanyEntity()..name = S.current.other_company);
      update();
    });
  }

  void onChangeAddress() {
    obtainContext?.call((context) async {
      AddressEntity entity = await showAddressBottomSheet(context, null,
          (String searchData) async {
        List<AddressEntity> addressList;
        await post(HttpCommonService.searchAddress(searchData),
            autoHandler: AutoHandler.Toast, onSuccess: (result) {
          addressList = getEntityFromResult<List<AddressEntity>>(result);
        });
        if (addressList == null) {
          addressList = [];
        }
        return addressList;
      });
      if (entity != null) {
        companyAddress = entity.address;
        postalCodeController.text = entity.code;
        update();
      }
    });
  }

  void onAddCreditCard() async {
    String paymentUrl;
    int subscriptionId;
    await post(HttpSubscriptionService.cardsNew(),
        loadingTip: S.current.loading,
        autoHandler: AutoHandler.Toast, onSuccess: (result) {
      paymentUrl = result.data['data']['payment_url'];
      subscriptionId = result.data['data']['subscription_id'];
    });
    if (paymentUrl != null) {
      final result =
          await Routes.navigateTo(RouterGenProviders.webViewPage, params: {
        'url': paymentUrl,
        'isAdd': true,
      });
      if (result is Map && result['isSeeInvoice'] == true) {
        loadCards(true);
        _loadPaymentMethod();
        obtainContext?.call((context) {
          Routes.navigateTo(RouterGenProviders.subInvoicePage, params: {
            'id': subscriptionId,
          });
        });
      } else if (result is Map && result['isSuccess'] == true) {
        loadCards(true);
        _loadPaymentMethod();
      }
    }
  }

  @override
  FutureOr<SubNextBillingItemEntity> transformData(
      SubNextBillingItemEntity d, bool isCache) {
    DateTime from = DateTime.tryParse(d.startAt);
    DateTime until = DateTime.tryParse(d.endAt);
    bool sameYear = from.year == until.year;

    billingPeriod =
        '${DateTimeUtils.formatDateTime(from, sameYear ? 'd MMM' : 'd MMM yyyy')} - ${DateTimeUtils.formatDateTime(until, 'd MMM yyyy')}';

    return super.transformData(d, isCache);
  }
}
